home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / interapplication comm / 7edit / source / sveditutils.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  17.1 KB  |  623 lines

  1. /*
  2.     File:        SVEditUtils.c
  3.  
  4.     Contains:    
  5.  
  6.     Written by: Original version by Jon Lansdell and Nigel Humphreys.
  7.                             3.1 updates by Greg Sutton.    
  8.  
  9.     Copyright:    Copyright ©1995-1999 by Apple Computer, Inc., All Rights Reserved.
  10.  
  11.                 You may incorporate this Apple sample source code into your program(s) without
  12.                 restriction. This Apple sample source code has been provided "AS IS" and the
  13.                 responsibility for its operation is yours. You are not permitted to redistribute
  14.                 this Apple sample source code as "Apple sample source code" after having made
  15.                 changes. If you're going to re-distribute the source, we require that you make
  16.                 it clear in the source that the code was descended from Apple sample source
  17.                 code, but that you've made changes.
  18.  
  19.     Change History (most recent first):
  20.                 7/19/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  21.                 10/12/95    CW                        Simplified FeatureIsImplemented routine.
  22.                                                                Added init of gHasDragManager flag in CheckEnvironment.
  23.                 
  24.  
  25. */
  26.  
  27. #include <DriverServices.h>
  28. #include <Events.h>
  29. #include <Traps.h>
  30. #include <Dialogs.h>
  31. #include <Fonts.h>
  32. #include <Packages.h>
  33. #include <ToolUtils.h>
  34. #include <AppleEvents.h>
  35. #include <CodeFragments.h>
  36. #include "SVEditUtils.h"
  37. #include <TextUtils.h>
  38.  
  39. /**-----------------------------------------------------------------------
  40.         Name:             LesserOf
  41.         Purpose:        Returns the Lesser of two longints.
  42.     -----------------------------------------------------------------------**/
  43. #pragma segment Utils
  44.         
  45. pascal long LesserOf(long A, long B)
  46.  {
  47.    if (A<B)
  48.        return(A);
  49.      else
  50.        return(B);
  51.  }   /*LesserOf*/
  52.             
  53. /**-----------------------------------------------------------------------
  54.         Name:             GreaterOf
  55.         Purpose:        Returns the Greater of two longints.
  56.     -----------------------------------------------------------------------**/
  57.     
  58. #pragma segment Utils
  59.         
  60. pascal long GreaterOf(long A, long B)
  61.  {
  62.    if (A>B)
  63.        return(A);
  64.      else
  65.        return(B);
  66.  }  /*GreaterOf*/
  67.             
  68. /**-----------------------------------------------------------------------
  69.         Name:             ShowError
  70.         Purpose:        Reports an error to the user as both string and number.
  71.     -----------------------------------------------------------------------**/
  72. #pragma segment Utils
  73.         
  74. pascal void ShowError(Str255  theError,
  75.                                           long    theErrorCode)
  76. {
  77.    short     alertResult;
  78.    Str255    theString;
  79.      OSErr     myErr;
  80.      
  81.      myErr = AEInteractWithUser(kAEDefaultTimeout, nil,nil);
  82.      
  83.      if (myErr == noErr)
  84.        {
  85.              SetCursor(&qd.arrow);
  86.              NumToString(theErrorCode, theString);
  87.              ParamText(theError, theString, (unsigned char *)"", (unsigned char *)"");
  88.              alertResult = Alert(300, nil);
  89.          }
  90. } /* ShowError */
  91.  
  92. /**-----------------------------------------------------------------------
  93.         Name:             Ours
  94.         Purpose:        Checks the frontmost window belongs to the app.
  95.     -----------------------------------------------------------------------**/
  96. #pragma segment Utils        
  97.     
  98. pascal Boolean Ours(WindowPtr aWindow)
  99.  {
  100.         if (aWindow)
  101.             if (((WindowPeek)aWindow)->windowKind == zoomDocProc)
  102.                 return(true);
  103.         return(false);
  104. } /* Ours */
  105.  
  106. /**-----------------------------------------------------------------------
  107.         Name:             SetShortMenus
  108.         Purpose:        Cuts the menus down to a minimum - Apple File Edit.
  109.                                 Greys out the unavailable options - used when no docs open
  110.     -----------------------------------------------------------------------**/
  111. #pragma segment Utils        
  112.  
  113. pascal void SetShortMenus()
  114.     DeleteMenu(mfontID);
  115.     DeleteMenu(sizeID);
  116.     DeleteMenu(styleID);
  117.  
  118.     DisableItem(myMenus[fileM], fmClose);
  119.     DisableItem(myMenus[fileM], fmSave);
  120.     DisableItem(myMenus[fileM], fmSaveAs);
  121.     DisableItem(myMenus[fileM], fmRevert);
  122.     DisableItem(myMenus[fileM], fmPageSetUp);
  123.     DisableItem(myMenus[fileM], fmNoGXPrint);
  124.  
  125.     /* now the unnecessary items on the edit menu */
  126.                 
  127.     DisableItem(myMenus[editM], undoCommand);
  128.     DisableItem(myMenus[editM], cutCommand);
  129.     DisableItem(myMenus[editM], copyCommand);
  130.     DisableItem(myMenus[editM], clearCommand);
  131.     DisableItem(myMenus[editM], pasteCommand);
  132.     DisableItem(myMenus[editM], selectAllCommand);
  133.  
  134.     DrawMenuBar();
  135. }  /* SetShortMenus */
  136.  
  137. /**-----------------------------------------------------------------------
  138.         Name:             SetLongMenus
  139.         Purpose:        Reinstates the full menu bar - called when first document
  140.                     opened.
  141.     -----------------------------------------------------------------------**/
  142. #pragma segment Utils        
  143.  
  144. pascal void SetLongMenus()
  145.   {
  146.         InsertMenu(myMenus[fontM], 0);
  147.         InsertMenu(myMenus[sizeM], 0);
  148.         InsertMenu(myMenus[styleM], 0);
  149.  
  150.         EnableItem(myMenus[fileM], fmClose);
  151.         EnableItem(myMenus[fileM], fmSave);
  152.         EnableItem(myMenus[fileM], fmSaveAs);
  153.         EnableItem(myMenus[fileM], fmRevert);
  154.         EnableItem(myMenus[fileM], fmPageSetUp);
  155.  
  156.         EnableItem(myMenus[fileM], fmNoGXPrint );
  157.  
  158.         /* now the necessary items on the edit menu -
  159.             many other items fixed on each pass thru the main event
  160.             loop or before the window pulled down
  161.         */
  162.         
  163.         EnableItem(myMenus[editM], selectAllCommand);
  164.  
  165.         DrawMenuBar();
  166.     }  /* SetLongMenus */
  167.  
  168. /**-----------------------------------------------------------------------
  169.         Name:             SetStyleMenu
  170.         Purpose:        Sets the style menu checking to reflect the style of the
  171.                     first character of the current selection in the given
  172.                                 document.
  173.     -----------------------------------------------------------------------**/
  174. #pragma segment Utils        
  175.         
  176. pascal void SetStyleMenu(DPtr theDoc)
  177.   {
  178.     TextStyle        theTStyle;
  179.         short       contMode;
  180.         short       i;
  181.         
  182.         contMode = doFace;
  183.         
  184.         TEContinuousStyle(&contMode,&theTStyle,theDoc->theText);
  185.         
  186.         if ((contMode & doFace) != 0)
  187.             {
  188.                 CheckItem(myMenus[styleM], cPlain,     (theTStyle.tsFace == 0));
  189.                 CheckItem(myMenus[styleM], cBold,      (bold      & theTStyle.tsFace));
  190.                 CheckItem(myMenus[styleM], cItalic,    (italic    & theTStyle.tsFace));
  191.                 CheckItem(myMenus[styleM], cUnderline, (underline & theTStyle.tsFace));
  192.                 CheckItem(myMenus[styleM], cOutline,   (outline   & theTStyle.tsFace));
  193.                 CheckItem(myMenus[styleM], cShadow,    (shadow    & theTStyle.tsFace));
  194.                 CheckItem(myMenus[styleM], cCondense,  (condense  & theTStyle.tsFace));
  195.                 CheckItem(myMenus[styleM], cExtend,    (extend    & theTStyle.tsFace));
  196.           }
  197.         else
  198.             for (i=cPlain; i<= cExtend; i++)
  199.                 CheckItem(myMenus[styleM], i,     false);
  200.   }
  201.  
  202. /**-----------------------------------------------------------------------
  203.     Name:       SetSizeMenu
  204.     Purpose:    Outline all the items if the current font is an
  205.                 outline font. Check the size of the current selection
  206.   -----------------------------------------------------------------------**/
  207. #pragma segment Utils        
  208.  
  209. pascal void SetSizeMenu(DPtr theDoc)
  210.   {
  211.       short             i;
  212.         short                aSize;
  213.         short                max;
  214.     long                 theSize;
  215.     Str255        name;
  216.     Boolean       sizeinMenu;
  217.     Boolean       oldState;
  218.     Point         numer;
  219.     TextStyle        theStyle;
  220.         TEHandle    myText;
  221.         short       contMode;
  222.       
  223.     numer.h = 1;
  224.     numer.v = 1;
  225.  
  226.     myText = theDoc->theText;
  227.         
  228.         contMode = doSize+doFont;
  229.         
  230.         TEContinuousStyle(&contMode,&theStyle,theDoc->theText);
  231.         
  232.     sizeinMenu = false;
  233.     max = CountMItems(myMenus[sizeM]);
  234.         for (i = 1; i <= max - 5; i++)
  235.       {
  236.                 GetMenuItemText(myMenus[sizeM], i, name);
  237.                 StringToNum(name, &theSize);
  238.                 aSize = (short)theSize;
  239.  
  240.                 if (RealFont(theStyle.tsFont, aSize) && (contMode & doFont) != 0) // there is only one font and this size exists
  241.                     SetItemStyle(myMenus[sizeM], i, outline);
  242.                 else
  243.                     SetItemStyle(myMenus[sizeM], i, 0);
  244.  
  245.                 if ((aSize == theStyle.tsSize) && (contMode & doSize) != 0)
  246.                     {
  247.                         sizeinMenu = true;
  248.                         CheckItem(myMenus[sizeM], i, true);
  249.                     }
  250.                 else
  251.                     CheckItem(myMenus[sizeM], i, false);
  252.             }
  253.         
  254.             /*
  255.                 if it's not a size in the menu,and there is only one size in the
  256.               selection range check the other item
  257.             */
  258.             
  259.             if (!sizeinMenu && (contMode & doSize) != 0)
  260.               CheckItem(myMenus[sizeM], max, true);
  261.             else
  262.                 CheckItem(myMenus[sizeM], max, false);
  263.  
  264.             /*if this is an outline font, set the rest of the items to outline style*/
  265.             /*RealFont will ensure that the sizes are outlined*/
  266.  
  267.             oldState = GetOutlinePreferred();
  268.             SetOutlinePreferred(true);
  269.             for (i = max-4; i <= max; i++)
  270.                 {
  271.                     if (IsOutline(numer, numer) && (contMode & doFont)!= 0)
  272.                         SetItemStyle(myMenus[sizeM], i, outline);
  273.                     else
  274.                         SetItemStyle(myMenus[sizeM], i, 0);
  275.                 }
  276.                 
  277.             SetOutlinePreferred(oldState);
  278.     }
  279.  
  280. /**-----------------------------------------------------------------------
  281.     Name:       SetFontMenu
  282.     Purpose:    Set the font menu according to the state of
  283.                                 current selection of the supplied document.
  284.   -----------------------------------------------------------------------**/
  285. #pragma segment Utils
  286.         
  287. pascal void SetFontMenu(DPtr theDoc)
  288.   {
  289.     MenuHandle        theMHandle;
  290.     short         theNumber;
  291.     short         i;
  292.     short                max;
  293.     Str255        name;
  294.     TextStyle     theStyle;
  295.         short         contMode;
  296.  
  297.         theMHandle = GetMenuHandle(mfontID);
  298.  
  299.         if (gFontMItem)
  300.       CheckItem(theMHandle, gFontMItem, false);
  301.             
  302.         max = CountMItems(theMHandle);
  303.  
  304.         contMode = doFont;
  305.         TEContinuousStyle(&contMode,&theStyle,theDoc->theText);
  306.  
  307.         gFontMItem = 0;
  308.         
  309.     if (contMode & doFont)
  310.             for (i=1; i<=max; i++)
  311.                 {
  312.                     GetMenuItemText(theMHandle, i, name);
  313.                     GetFNum(name, &theNumber);
  314.                     if (theNumber == theStyle.tsFont)
  315.                         gFontMItem = i;
  316.                 }
  317.  
  318.     if (gFontMItem)
  319.       CheckItem(theMHandle, gFontMItem, true);
  320.             
  321.         SetSizeMenu(theDoc);
  322.         SetStyleMenu(theDoc);
  323.     }
  324.  
  325. /**-----------------------------------------------------------------------
  326.     Name:       GetTempFileName
  327.     Purpose:    Fills newstring with a temporary file name.
  328.   -----------------------------------------------------------------------**/
  329.  
  330. #pragma segment Utils
  331.  
  332. pascal void GetTempFileName(DPtr aDoc,
  333.                             Str255 newString)
  334.  
  335.     {
  336.        Str255        s;
  337.      Str255        fileName;
  338.  
  339.         if (aDoc->everSaved == false)
  340.           PStrCopy(fileName, (unsigned char *)"\pTEXTra");
  341.         else
  342.             PStrCopy(fileName, aDoc->theFileName);
  343.  
  344.     /*generate a unique(ish) temporary filename*/
  345.         
  346.         if (fileName[0] > 21)
  347.           fileName[0] = 21;
  348.                 
  349.         NumToString(TickCount(), s);
  350.         
  351.         PStrCat(fileName, s);
  352.         
  353.         PStrCopy(newString,fileName);
  354.     }
  355.  
  356. /**-----------------------------------------------------------------------
  357.     Name:       SetText
  358.     Purpose:    Sets the text of the supplied itemNo in aDialog to 
  359.                                 theString and select it.
  360.   -----------------------------------------------------------------------**/
  361.  
  362. #pragma segment Utils
  363.  
  364. pascal void SetText(DialogPtr aDialog,
  365.                     short     itemNo,
  366.                     Str255    theString)
  367.   {
  368.     Handle      itemHandle;
  369.     Rect        box;
  370.     short       kind;
  371.     TEHandle    theTEHandle;
  372.  
  373.         GetDialogItem(aDialog, itemNo, &kind, &itemHandle, &box);
  374.         SetDialogItemText(itemHandle, theString);
  375.         
  376.         theTEHandle = ((DialogPeek)aDialog)->textH;
  377.  
  378.         /*set all the text to be selected*/
  379.         if (theTEHandle)
  380.             TESetSelect(0, 255, theTEHandle);
  381.     }
  382.             
  383. /**-----------------------------------------------------------------------
  384.     Name:       RetrieveText
  385.     Purpose:    Returns the text of anItem in aDialog in aString.
  386.   -----------------------------------------------------------------------**/
  387.  
  388. #pragma segment Utils
  389.  
  390. pascal void RetrieveText(DialogPtr aDialog,
  391.                                                short     anItem,
  392.                                                Str255    aString)
  393.   {
  394.      short      kind;
  395.      Rect       box;
  396.      Handle     itemHandle;
  397.  
  398.          GetDialogItem(aDialog, anItem, &kind, &itemHandle, &box);
  399.          GetDialogItemText(itemHandle, aString);
  400.   }
  401.  
  402. /**-----------------------------------------------------------------------
  403.     Name:       DrawDefaultOutline
  404.     Purpose:    Draws an outline around theItem.
  405.                                 Called as a useritem Proc by the dialog manager.
  406.                                 To use place a useritem over the default item in the
  407.                                 dialog and install the address of this proc as the item
  408.                                 handle.
  409.   -----------------------------------------------------------------------**/
  410.  
  411. #pragma segment Utils
  412.  
  413. pascal void DrawDefaultOutline(DialogPtr theDialog, short theItem)
  414.   {
  415.       short       kind;
  416.     Handle      itemHandle;
  417.     Rect        box;
  418.                 
  419.     GetDialogItem(theDialog, theItem, &kind, &itemHandle, &box);
  420.     PenSize(3, 3);
  421.     InsetRect(&box, - 4, - 4);
  422.     FrameRoundRect(&box, 16, 16);
  423.     PenNormal();
  424.         
  425.     }  /* DrawDefaultOutline */
  426.             
  427. /**-----------------------------------------------------------------------
  428.     Name:       AdornDefaultButton
  429.     Purpose:    Installs DrawDefaultOutline as the useritem proc
  430.                     for the given item.
  431.   -----------------------------------------------------------------------**/
  432.  
  433. #pragma segment Utils
  434.         
  435. pascal void AdornDefaultButton(DialogPtr theDialog,short theItem)
  436.   {
  437.       short       kind;
  438.     Handle      itemHandle;
  439.     Rect        box;
  440.  
  441.         GetDialogItem(theDialog, theItem, &kind, &itemHandle, &box);
  442.         SetDialogItem(theDialog, theItem, kind, (Handle)gDefaultButtonUPP, &box);
  443.   }
  444.  
  445.     /*-------  Determining of Gestalt is available ---------------*/
  446.     /*The following routines come from the Inside Mac VI recommendations*/
  447.     /*about how to find if a trap is available*/
  448.          /*
  449.             The glue for Gestalt will be in MPW 3.2, so if it is available we will also
  450.              need to check the system version
  451.         */
  452.  
  453. pascal void GetRectOfDialogItem(DialogPtr theDialog, short theItem, Rect *theRect)
  454.     {
  455.       short       kind;
  456.     Handle      itemHandle;
  457.         
  458.         GetDialogItem(theDialog, theItem, &kind, &itemHandle, theRect);
  459.     }
  460.  
  461. #pragma segment Utils
  462.  
  463. pascal short NumToolboxTraps(void)
  464.   {
  465.         if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  466.             return(0x200);
  467.         else
  468.             return(0x400);
  469.     }
  470.  
  471. #pragma segment Utils
  472.  
  473. #define TrapMask  0x0800
  474.  
  475. pascal TrapType GetTrapType(short theTrap)
  476.   {
  477.         if ((theTrap & TrapMask) > 0)
  478.             return(ToolTrap);
  479.         else
  480.             return(OSTrap);
  481.     }
  482.  
  483. #pragma segment Utils
  484.  
  485. pascal Boolean TrapAvailable(short theTrap)
  486.   {
  487.         TrapType  tType;
  488.  
  489.         tType = GetTrapType(theTrap);
  490.         if (tType == ToolTrap)
  491.             {
  492.                 theTrap = theTrap & 0x07FF;
  493.                 if (theTrap >= NumToolboxTraps())
  494.                     theTrap = _Unimplemented;
  495.             }
  496.         return(NGetTrapAddress(theTrap, tType) != NGetTrapAddress(_Unimplemented,ToolTrap));
  497.     }
  498.  
  499. #pragma segment Utils
  500.  
  501. #define _Gestalt 0xA1AD
  502.  
  503. pascal Boolean GestaltAvailable()
  504.   {
  505.         return(TrapAvailable(_Gestalt));
  506.     }
  507.  
  508. /**------  FeatureIsImplemented    ------------**/
  509. /*This is called to use Gestalt to determine if a feature is implemented.
  510.  This applies to only those referenced by OSType*/
  511.  
  512. #pragma segment Utils
  513.  
  514.  
  515. pascal Boolean FeatureIsImplemented ( OSType theFeature, short theTestBit )
  516. {
  517.     OSErr     err;
  518.     long      result;
  519.  
  520.     err = Gestalt ( theFeature, &result );
  521.     return (err == noErr && (result & (1L << theTestBit)));
  522.     
  523. }
  524.  
  525.  
  526.  
  527.  
  528. #pragma segment Utils
  529.  
  530. pascal Boolean CheckEnvironment()
  531.   {
  532.         /*
  533.          first determine of Gestalt is available- if it isn't exit
  534.          as we only run under 7.0.  It could it present in 6.04 - so we need
  535.          to do some further checks for important features
  536.         */
  537.  
  538.         gGestaltAvailable = GestaltAvailable();
  539.         
  540.         if (!gGestaltAvailable)
  541.             return(false);
  542.  
  543.     /*first check if the Edition Manager is present*/
  544.                 
  545.     gEditionManagerImplemented = FeatureIsImplemented(gestaltEditionMgrAttr,
  546.                                                                                                           gestaltEditionMgrPresent);
  547.  
  548.         /*and for good measure- the Alias manager*/
  549.                 
  550.         gAliasManagerImplemented  = FeatureIsImplemented(gestaltAliasMgrAttr,
  551.                                                                                                          gestaltAliasMgrPresent);
  552.             
  553.         /*check for the AppleEvents manager - we certainly can't work without it*/
  554.         
  555.         gAppleEventsImplemented   = FeatureIsImplemented(gestaltAppleEventsAttr,
  556.                                                                                                          gestaltAppleEventsPresent);
  557.         
  558.         /*check if recording is implemented*/
  559.         
  560.         gRecordingImplemented   = FeatureIsImplemented(gestaltAppleEventsAttr,1);
  561.             
  562.         /*check for the Outline fonts*/
  563.         
  564.         gOutlineFontsImplemented  = FeatureIsImplemented(gestaltFontMgrAttr,
  565.                                                                                                          gestaltOutlineFonts);
  566.         
  567.     
  568.     // We would also like the Drag Manager
  569.     gHasDragManager = FeatureIsImplemented ( gestaltDragMgrAttr, gestaltDragMgrPresent );
  570.     
  571.     // It isn't enough to use Gestalt because we may not have sucessfully linked
  572.     // to the DragLib shared library. So, we also need to test one of the symbols
  573.     // against kUnresolvedSymbol to make sure we have a valid connection to it.
  574.     
  575. #if GENERATINGCFM
  576.     if ( gHasDragManager )
  577.         gHasDragManager = (InstallTrackingHandler != (void*) kUnresolvedCFragSymbolAddress);
  578. #endif
  579.  
  580.  
  581.         return (gEditionManagerImplemented &&
  582.                         gAliasManagerImplemented   &&
  583.                         gAppleEventsImplemented    &&
  584.                         gOutlineFontsImplemented);
  585.                                 
  586.     }  /* CheckEnvironment */
  587.             
  588.     /*
  589.         DoPageSetup returns true if the page setup of the document is altered
  590.     */
  591.     
  592.     pascal Boolean DoPageSetup(DPtr theDoc)
  593.         {
  594.             Boolean result = false;
  595.                 if (theDoc)
  596.                         {
  597.                             PrOpen();
  598.                             result =  PrStlDialog(theDoc->thePrintSetup);
  599.                             PrClose();
  600.                         }
  601.                     
  602.                 return(result);
  603.         }  /* DoPageSetup */
  604.  
  605. /*
  606.     Name:    CtrlKeyPressed
  607.     Purpose: Returns true if control key pressed during event
  608. */
  609. pascal Boolean CtrlKeyPressed(const EventRecord *theEvent)
  610.     {
  611.         return((theEvent->modifiers & controlKey) != 0);
  612.     }
  613.     
  614. /*
  615.     Name:    OptionKeyPressed
  616.     Purpose: Returns true if option key pressed during event
  617. */
  618. pascal Boolean OptionKeyPressed(const EventRecord *theEvent)
  619.     {
  620.         return((theEvent->modifiers & optionKey) != 0);
  621.     }
  622.